/*
 * screenCoords.java
 * Objetc to store the coordinates of the moons.
 * Implements methods to sort, invert and rotate the data in the screen.
 *
 * Copyright 2009 by Miguel Moreto.
 * You may use or distribute this code under the terms of the GPL.
 * 
 * $Rev: 54 $
 * $LastChangedDate: 2009-07-15 14:22:06 +0000 (Wed, 15 Jul 2009) $
 */

package Main;


import java.util.*;
/**
 *
 * @author Moreto
 */
public class screenCoords {

    Vector X = new Vector();        //X coordinate of the objetc.
    Vector Y = new Vector();        //Y coordinate of the objetc.
    Vector Radius = new Vector();   //Radius of the object's orbit.
    Vector Names = new Vector();    //Name of the object.
    Vector Type = new Vector();     //Type of the object (0=moon, 1=shadow).
    Vector screenX = new Vector();  // Screen X coordinates of the objects.
    Vector screenY = new Vector();  // Screen Y coordinates of the objects.
    int w;      // Screen width.
    int h;     // Screen height.
    int Wc;    // Screen X (width) center value.
    int Hc;    // Screen Y (height) center value.
    double js;       // Jupiter size.
    double jsfactor = 1; // Jupiter size scale factor.
    int moonRadius;
    int margin;

    //constructor:
   public screenCoords(int width, int height, int widthcenter, int heightcenter, 
           int moonRad, double zoonfactor,int screenmargin) {
	w = width;
	h = height;
        Wc = widthcenter;
        Hc = heightcenter;
        moonRadius = moonRad;
        jsfactor = zoonfactor;
        margin = screenmargin;
    }

//<editor-fold defaultstate="collapsed" desc=" sortData method ">
    /*
     * Method to sort the data in crescent order of x coordinate.
     */
    void sortData(){

        for (int i=0; i<(X.size() - 1); i++){
            for (int j=(i+1); j < (X.size()); j++){
                if (((Double)X.elementAt(i)).doubleValue() > ((Double)X.elementAt(j)).doubleValue()){
                    Object Xtmp = X.elementAt(i);
                    Object Ytmp = Y.elementAt(i);
                    Object Ntmp = Names.elementAt(i);
                    Object Rtmp = Radius.elementAt(i);
                    Object Ttmp = Type.elementAt(i);
                    X.setElementAt(X.elementAt(j), i);
                    Y.setElementAt(Y.elementAt(j), i);
                    Names.setElementAt(Names.elementAt(j), i);
                    Radius.setElementAt(Radius.elementAt(j), i);
                    Type.setElementAt(Type.elementAt(j), i);
                    X.setElementAt(Xtmp, j);
                    Y.setElementAt(Ytmp, j);
                    Names.setElementAt(Ntmp, j);
                    Radius.setElementAt(Rtmp, j);
                    Type.setElementAt(Ttmp, j);
                }
            }
        }
    }
//</editor-fold>


    void calculateScreenCoords(double alfa){
        /*
         * It works well for alfa angles between 0 and Pi/2.
         */

        double a1 = Math.tan(alfa)*(double)Hc;
        double b1 = Math.tan(Math.PI/2 - alfa)*(double)Wc;
        double a2 = Math.tan(alfa)*(double)(h-Hc);
        double b2 = Math.tan(Math.PI/2 - alfa)*(double)(w-Wc);

        
        double x1 = Math.min(a1, Wc);
        double x1c = Wc - x1;
        
        double y1 = Math.min(b1, Hc);
        double y1c = Hc - y1;
        
        screenX.addElement(new Double(x1c));
        screenY.addElement(new Double(y1c));

        // Lower right coordinates corner of the rotated screen:
        double x2 = Math.min(a2, (w-Wc));
        double x2c = x2 + Wc;
        
        double y2 = Math.min(b2, (h-Hc));
        double y2c = y2 + Hc;
       
        screenX.addElement(new Double(x2c));
        screenY.addElement(new Double(y2c));

        // Width of the rotated screen:
        double newWidth = Math.sqrt(x1*x1+y1*y1)+Math.sqrt(x2*x2+y2*y2) - 2*margin;

        // Size of Jupiter:
        js = ((newWidth/2)* 71492)/1882709;

        for (int i=0; i<(X.size()); i++){

            // Moon coordinates scalled according to jupiter radius:
            double xs = (((Double)X.elementAt(i)).doubleValue() * js * jsfactor);
            double ys = (((Double)Y.elementAt(i)).doubleValue() * js * jsfactor);

            // Calculating the new Xs and Ys coordinates in the rotated screen:
            double beta = mMath.atan(ys / xs);
            
            double H = Math.sqrt(xs*xs + ys*ys);

            //
            // This functions have a bug. It does not take into account the
            // signal from the ys coordinate of the moon.
            double Xs = Wc - H*Math.sin(alfa - beta)- moonRadius/2;
            double Ys = Hc - H*Math.cos(alfa - beta)- moonRadius/2;

            if (xs >= 0.0){
                Xs = Wc + H*Math.sin(alfa - beta)- moonRadius/2;
                Ys = Hc + H*Math.cos(alfa - beta)- moonRadius/2;
            }
            screenX.addElement(new Double(Xs));
            screenY.addElement(new Double(Ys));
        }


    }
    /*
     * Method to append an element into the data vectors.
     */
    void appendData(double x, double y, String name, double radius, boolean type){
        X.addElement(new Double(x));
        Y.addElement(new Double(y));
        Names.addElement(new String(name));
        Radius.addElement(new Double(radius));
        Type.addElement(new Boolean(type));
    }

    /*
     * Method to invert the moon's positions horizontaly
     */
    void invertHorizontal(){
        for (int i=0; i<(X.size()); i++){
            double xtmp = ((Double)X.elementAt(i)).doubleValue();
            X.setElementAt(new Double(-xtmp), i);
        }
        //X.setElementAt(new Double((d+m) * Math.sin(angle)), i);
    }

    /*
     * Method to invert the moon's positions horizontaly
     */
    void invertVertical(){
        for (int i=0; i<(Y.size()); i++){
            double ytmp = ((Double)Y.elementAt(i)).doubleValue();
            Y.setElementAt(new Double(-ytmp), i);
        }
    }
    /*
     * Getter methods:
     */
    int getSize(){
        return X.size();
    }
    double getXcoord(int i){
        return ((Double)X.elementAt(i)).doubleValue();
    }
    double getYcoord(int i){
        return ((Double)Y.elementAt(i)).doubleValue();
    }
    double getScreenXcoord(int i){
        return ((Double)screenX.elementAt(i)).doubleValue();
    }
    double getScreenYcoord(int i){
        return ((Double)screenY.elementAt(i)).doubleValue();
    }
    String getName(int i){
        return (String)Names.elementAt(i);
    }
    double getRadius(int i){
        return ((Double)Radius.elementAt(i)).doubleValue();
    }
    boolean getType(int i){
        return ((Boolean)Type.elementAt(i)).booleanValue();
    }
    int getJs(){
        return (int)(js * jsfactor);
    }
}

